-- local msgserver = require "snax.msgserver"
-- local crypt = require "skynet.crypt"
-- local skynet = require "skynet"

-- local subid = 0
-- local server = {}  --一张表，里面需要实现前面提到的所有回调接口
-- local servername
-- --外部发消息来调用，一般用来注册可以登陆的登录名
-- function server.login_handler(uid, secret) 
--     skynet.error("login_handler invoke", uid, secret)
--     subid = subid + 1
--      --通过uid以及subid获得username
--     local username = msgserver.username(uid, subid, servername)
--     skynet.error("uid",uid, "login，username", username)
--     msgserver.login(username, secret)--正在登录，给登录名注册一个secret
--     return subid
-- end

-- --外部发消息来调用，注销掉登陆名
-- function server.logout_handler(uid, subid)
--     skynet.error("logout_handler invoke", uid, subid)
--     local username = msgserver.username(uid, subid, servername)
--     msgserver.logout(username)
-- end

-- --外部发消息来调用，用来关闭连接
-- function server.kick_handler(uid, subid)
--     skynet.error("kick_handler invoke", uid, subid)
-- end

-- --当客户端断开了连接，这个回调函数会被调用
-- function server.disconnect_handler(username) 
--     skynet.error(username, "disconnect")
-- end

-- --当接收到客户端的请求，这个回调函数会被调用,你需要提供应答。
-- function server.request_handler(username, msg)
--     skynet.error("recv", msg, "from", username)
--     return string.upper(msg)
-- end

-- --监听成功会调用该函数，name为当前服务别名
-- function server.register_handler(name)
--     skynet.error("register_handler invoked name", name)
--     servername = name
-- end

-- msgserver.start(server) --需要配置信息

-- local msgserver = require "snax.msgserver"
-- local crypt = require "skynet.crypt"
-- local skynet = require "skynet"

-- local loginservice = tonumber(...) --从启动参数获取登录服务的地址
-- local server = {}  --一张表，里面需要实现前面提到的所有回调接口
-- local servername
-- local subid = 0

-- --外部发消息来调用，一般是loginserver发消息来，你需要产生唯一的subid，如果loginserver不允许multilogin，那么这个函数也不会重入。
-- function server.login_handler(uid, secret)
--     subid = subid + 1
--     --通过uid以及subid获得username
--     local username = msgserver.username(uid, subid, servername)
--     skynet.error("uid",uid, "login，username", username)
--     msgserver.login(username, secret)--正在登录，给登录名注册一个secret
--     return subid
-- end

-- --外部发消息来调用，登出uid对应的登录名
-- function server.logout_handler(uid, subid)
--     local username = msgserver.username(uid, subid, servername)
--     msgserver.logout(username) --登出
-- end

-- --一般给loginserver发消息来调用，可以作为登出操作
-- function server.kick_handler(uid, subid)
--     server.logout_handler(uid, subid)
-- end

-- --当客户端断开了连接，这个回调函数会被调用
-- function server.disconnect_handler(username) 
--     skynet.error(username, "disconnect")
-- end

-- --当接收到客户端的网络请求，这个回调函数会被调用，需要给与应答

-- -- 在服务mymsgserver中的接收到请求后，会自动剥离协议中的len以及session，得到请求内容，如果
-- -- 在处理请求内容的时候，应答出现异常，那么会返回ok的值为0.
-- -- $ 3rd/lua/lua my_workspace/myclient.lua
-- -- sceret is   a572bd350328d80d
-- -- 200 MQ==
-- -- login ok, subid=    1
-- -- connect
-- -- 200 OK
-- -- ===>    echo    0
-- -- disconnect
-- -- connect
-- -- 200 OK
-- -- ===>    fake    0
-- -- ===>    again   1
-- -- <===    false       0   #返回false 并且没有响应内容
-- -- <===    false       1   #返回false 并且没有响应内容
-- -- disconnect
-- function server.request_handler(username, msg)
--     skynet.error("recv", msg, "from", username)
--     error("request_handler")
--     return string.upper(msg)
-- end

-- --注册一下登录点服务，主要是告诉loginservice这个有这个登录点的存在
-- function server.register_handler(name)
--     servername = name
--     skynet.call(loginservice, "lua", "register_gate", servername, skynet.self())
-- end

-- msgserver.start(server) --需要配置信息表server


-- $ ./skynet examples/conf
-- testmsgserver
-- [:01000010] LAUNCH snlua testmsgserver
-- [:01000012] LAUNCH snlua mylogin
-- [:01000019] LAUNCH snlua mylogin
-- [:0100001a] LAUNCH snlua mylogin
-- [:0100001b] LAUNCH snlua mylogin
-- [:0100001c] LAUNCH snlua mylogin
-- [:0100001d] LAUNCH snlua mylogin
-- [:0100001e] LAUNCH snlua mylogin
-- [:0100001f] LAUNCH snlua mylogin
-- [:01000020] LAUNCH snlua mylogin
-- [:01000012] login server listen at : 127.0.0.1 8001
-- [:01000022] LAUNCH snlua mymsgserver 16777234
-- [:01000022] Listen on 0.0.0.0:8002
-- register_handler  
-- [:01000012] cmd register_gate sample #loginserver register_gate调用
-- [:01000019] connect from 127.0.0.1:48822 (fd = 10) #loginserver有新连接产生
-- [:01000019] nzhsoft@sample:password  #loginserver author_handler调用
-- [:01000012] nzhsoft@sample is login, secret is 2828d352698fff21 # loginserver login_handler调用
-- [:01000022] uid nzhsoft login，username bnpoc29mdA==@c2FtcGxl#MQ== #msgserver login_handler调用
-- [:01000022] recv echo from bnpoc29mdA==@c2FtcGxl#MQ== #msgserver接收到消息并且应答
-- [:01000022] bnpoc29mdA==@c2FtcGxl#MQ== disconnect  #断开连接，调用msgserver的logout_handler函数。


local msgserver = require "snax.msgserver"
local crypt = require "skynet.crypt"
local skynet = require "skynet"

local loginservice = tonumber(...) --从启动参数获取登录服务的地址
local server = {}  --一张表，里面需要实现前面提到的所有回调接口
local servername
local subid = 0
local agents = {}

function server.login_handler(uid, secret) 
    subid = subid + 1
    local username = msgserver.username(uid, subid, servername)--通过uid以及subid获得username
    skynet.error("uid",uid, "login，newusername", username)
    msgserver.login(username, secret)--正在的登录
    local agent = skynet.newservice("mymsgagent")
    skynet.call(agent, "lua", "login", uid, subid, secret)
    agents[username] = agent
    return subid
end

--一般给agent调用
function server.logout_handler(uid, subid)
    local username = msgserver.username(uid, subid, servername)
    msgserver.logout(username) --登出
    skynet.call(loginservice, "lua", "logout",uid, subid) --通知一下loginservice已经退出
    agents[username] = nil
end

--一般给loginserver调用
function server.kick_handler(uid, subid)
    local username = msgserver.username(uid, subid, servername)
    local agent = agents[username]
    if agent then
        --这里使用pcall来调用skynet.call避免由于agent退出造成异常发生
        pcall(skynet.call, agent, "lua", "logout") --通知一下agent，让它退出服务。  
    end
end

--当客户端断开了连接，这个回调函数会被调用
function server.disconnect_handler(username) 
    skynet.error(username, "disconnect")
end

--当接收到客户端的请求，跟gateserver一样需要转发这个消息给agent，不同的是msgserver还需要response返回值
--，而gateserver并不负责这些事
function server.request_handler(username, msg)
    skynet.error("recv", msg, "from", username)
    --返回值必须是字符串，所以不管之前的数据是否是字符串，都转换一遍
    return skynet.tostring(skynet.rawcall(agents[username], "client", msg)) 
end

--注册一下登录点服务，主要是考诉loginservice这个登录点
function server.register_handler(name)
    servername = name
    skynet.call(loginservice, "lua", "register_gate", servername, skynet.self())
end

msgserver.start(server) --需要配置信息，跟gateserver一样,端口、ip，外加一个登录点名称
